/*
 * Util.java
 * Copyright (C) 2008 http://anphoralhrod.blogspot.com
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 3 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the Free
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 * 
 */

package Util;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Enumeration;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

/**
 *
 * @author fran
 */
public class Util {
    
    private static String linuxDesktop = null;

    /**
     * Obtiene el valor de una variable de entorno del sistema
     * @param envvar nombre de la variable de entorno
     * @return devuelve el valor de la variable de entorno
     */
    private static String getEnv(String envvar){
        try
        {
            Process p = Runtime.getRuntime().exec("printenv " + envvar);
            BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
            String value = br.readLine();
            return (value == null) ? "" : value.trim();
        } catch (IOException ex) {
            Logger.getLogger(Util.class.getName()).log(Level.SEVERE, null, ex);
            return "";
        }
    }

    /**
     * Obtiene el nombre del escritorio de linux sobre el que se ejecuta la aplicacion, solo kde y gnome
     * @return Devuelve el nombre de escritorio
     */
    private static String getLinuxDesktop(){
        //sólo se averigua el entorno de escritorio una vez, después se almacena en la variable estática
        if (linuxDesktop!=null) 
            return linuxDesktop;
        if (!getEnv("KDE_FULL_SESSION").equals("") || !getEnv("KDE_MULTIHEAD").equals(""))
            return "kde";

        else if(!getEnv("GNOME_DESKTOP_SESSION_ID").equals("") || !getEnv("GNOME_KEYRING_SOCKET").equals(""))
            return "gnome";

        return "";
    }

    /**
     * Lanza un navegador con una direccion url
     * @param url URL a cargar
     * @return true si la operacion tiene exito, false en otro caso
     */
    public static boolean launchURL(String url)
    {
        if (java.awt.Desktop.isDesktopSupported())
        {
            try {
                java.awt.Desktop.getDesktop().browse(new URI(url));
                return true;
            } catch (URISyntaxException ex) {
                Logger.getLogger(Util.class.getName()).log(Level.SEVERE, null, ex);
            } catch (IOException ex) {
                Logger.getLogger(Util.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        
        return launchURLBySO(url) != null;
    }
    
    /**
     * Analiza el SO en el cual se ejecuta la aplicacion y se lanza un navegador con la URL
     * @param url URL a lanzar
     * @return el proceso derivado de la ejecucion del navegador
     */
    private static Process launchURLBySO(String url)
    {
            String osName = System.getProperty("os.name").toLowerCase();
            
            if (osName.indexOf("linux") != -1)
            {
                String []param = null;
                if (getLinuxDesktop().equals("kde"))
                    param = new String[]{"kfmclient", "exec", url};
                else
                    param = new String[]{"gnome-open", url};
                
                try {
                    return Runtime.getRuntime().exec(param);
                } catch (IOException ex) {
                    Logger.getLogger(Util.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
            
            if (osName.indexOf("windows") != -1)
            {                
                try {
                    return Runtime.getRuntime().exec( new String[] { (osName.indexOf("95") != -1) ? "command.com" : "cmd.exe", "/C", "start", url});
                } catch (IOException ex) {
                    Logger.getLogger(Util.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
            
            if  (osName.indexOf("mac") != -1)
            {
                try {
                    return Runtime.getRuntime().exec(new String[]{"open", url});
                } catch (IOException ex) {
                    Logger.getLogger(Util.class.getName()).log(Level.SEVERE, null, ex);
                }
            }

        return null;
    }
    
    private static int BUFFER = 2046;
    
    /**
     *  Descomprime en el directorio de trabajo un fichero comprimido
     * @param filePath Path hasta el fichero comprimido
     * @throws java.io.IOException Si no se puede acceder al fichero comprimido
     */
    public static void unzip(String filePath) throws IOException
    {
        unzip(filePath, "");
    }
    
    /**
     * Descomprime un fichero zip en un directorio determinado
     * @param filePath Path hasta el fichero comprimido
     * @param destPath Path hacia donde se desea descomprimir el fichero
     * @throws java.io.IOException Si no se puede acceder al fichero comprimido o si el path de destino no existe o no es un directorio
     */
    public static void unzip(String filePath, String destPath) throws IOException
    {
        byte data[] = new byte[BUFFER];
        int count;
        BufferedOutputStream dest = null;
        BufferedInputStream is = null;
        ZipEntry entry;
        FileOutputStream fos;
        String outPath, tmpPath;
        
        if (!new File(filePath).exists())
            throw new IOException("\"" + filePath + "\" not exist.");
        
        if (!destPath.equals(""))
        {
            if (!destPath.endsWith(File.separator))
                destPath += File.separator;
            File tmp = new File(destPath);
            if (!tmp.exists() || !tmp.isDirectory())
                throw new IOException("\"" + destPath + "\" not exist or not is a directory.");
        }
        
        try 
        {
                ZipFile zipfile = new ZipFile(filePath);

                Enumeration e = zipfile.entries();
                while(e.hasMoreElements()) 
                {
                    entry = (ZipEntry) e.nextElement();
                    
                    tmpPath = entry.getName().replace("/", File.separator);
                    outPath = destPath + tmpPath;
                    if (!entry.isDirectory())
                    {
                        if (tmpPath.indexOf(File.separator) != -1)
                            new File(outPath).getParentFile().mkdirs();

                        is = new BufferedInputStream(zipfile.getInputStream(entry));
                        fos = new FileOutputStream(outPath);
                        dest = new BufferedOutputStream(fos, BUFFER);

                        while ((count = is.read(data, 0, BUFFER)) != -1)
                            dest.write(data, 0, count);

                        dest.flush();
                        dest.close();
                        is.close();
                    }
                    else
                        new File(outPath).getParentFile().mkdirs();
                }
        } catch(Exception e) {
            e.printStackTrace();
        }
    }
}

